﻿using System;

namespace Web7.Logging
{
	/*
	 * 按照逻辑需要，此类的一些重载方法的参数签名并未严格遵守 .NET 重载设计规范。
	 */

	/// <summary>
	/// 日志记录工具应该提供的功能接口
	/// </summary>
	public interface ILogger
	{
		/// <summary>
		/// 检查是否对某一级别启用了日志
		/// </summary>
		bool IsEnabled(OperationProcessLevel level);
		
		/// <summary>
		/// 记录异常信息[供 异常处理机制调用]，使用异常的级别来记录异常
		/// <remarks>
		/// 一般来说，不建议直接调用此方法，而应该调用系统中的异常处理机制的 <seealso cref="Exception.Publish"/> 扩展方法
		/// </remarks>
		/// </summary>
		/// <param name="exception">要记录的异常</param>
		void Log(Exception exception);
		/// <summary>
		/// 记录异常信息[供 异常处理机制调用]，使用指定的级别来记录异常
		/// <remarks>
		/// 一般来说，不建议直接调用此方法，而应该调用系统中的异常处理机制的 <seealso cref="Exception.Publish"/> 扩展方法
		/// </remarks>
		/// </summary>
		/// <param name="exception">要记录的异常</param>
		/// <param name="level">要指定用于记录异常的级别</param>
		void Log(Exception exception, OperationProcessLevel level);

		void Log(string message, Exception exception, OperationProcessLevel level);

		/// <summary>
		/// 采用默认级别记录一条日志消息
		/// </summary>
		/// <param name="message">要记录的消息</param>
		void Log(string message);
		/// <summary>
		/// 采用指定级别记录一条日志消息
		/// </summary>
		/// <param name="message">要记录的消息</param>
		/// <param name="level">要指定的级别</param>
		void Log(string message, OperationProcessLevel level);

		/// <summary>
		/// 按指定格式记录日志
		/// </summary>
		/// <param name="format">格式串</param>
		/// <param name="args">元字符串</param>
		void LogFormat(string format, params object[] args);
		/// <summary>
		/// 按指定格式记录日志
		/// </summary>
		/// <param name="level">要指定的级别</param>
		/// <param name="format">格式串</param>
		/// <param name="args">元字符串</param>
		void LogFormat(OperationProcessLevel level, string format, params object[] args);
	}

	public static class LoggerExtension
	{

		/// <summary>
		/// 调用指定Infomation 级别的用于生成日志消息的回调并记录最终结果
		/// </summary>
		/// <param name="messageGetter">用于生成日志消息的回调函数</param>
		public static void Log(this ILogger logger, Func<String> messageGetter)
		{
			logger.Log(messageGetter, OperationProcessLevel.Infomation);
		}

		/// <summary>
		/// 调用指定用于生成日志消息的回调并记录最终结果，记录时使用指定的级别
		/// </summary>
		/// <param name="messageGetter">用于生成日志消息的回调函数</param>
		/// <param name="level">要指定的用于记录日志的级别</param>
		public static void Log(this ILogger logger, Func<String> messageGetter, OperationProcessLevel level)
		{
			if (!logger.IsEnabled(level))
			{
				return;
			}

			var message = String.Empty;
			if (null != messageGetter)
			{
				message = messageGetter.Invoke();
			}
			logger.Log(message, level);
		}

		/// <summary>
		/// 记录异常信息[供 异常处理机制调用]，使用异常的级别来记录异常
		/// <remarks>
		/// 一般来说，不建议直接调用此方法，而应该调用系统中的异常处理机制的 <seealso cref="Exception.Publish"/> 扩展方法
		/// </remarks>
		/// </summary>
		public static void Error(this ILogger logger, Exception exception)
		{
			logger.Log(exception, OperationProcessLevel.Error);
		}
		/// <summary>
		/// 记录异常信息[供 异常处理机制调用]，使用异常的级别来记录异常
		/// <remarks>
		/// 一般来说，不建议直接调用此方法，而应该调用系统中的异常处理机制的 <seealso cref="Exception.Publish"/> 扩展方法
		/// </remarks>
		/// </summary>
		public static void Error(this ILogger logger, string message)
		{
			logger.Log(message, OperationProcessLevel.Error);
		}

		/// <summary>
		/// 记录异常信息[供 异常处理机制调用]，使用异常的级别来记录异常
		/// <remarks>
		/// 一般来说，不建议直接调用此方法，而应该调用系统中的异常处理机制的 <seealso cref="Exception.Publish"/> 扩展方法
		/// </remarks>
		/// </summary>
		public static void Error(this ILogger logger, string message, Exception exception)
		{
			logger.Log(message, exception, OperationProcessLevel.Error);
		}

		public static void Fatal(this ILogger logger, Exception exception)
		{
			logger.Log(exception, OperationProcessLevel.Fatal);
		}

		public static void Fatal(this ILogger logger, string message, Exception exception)
		{
			logger.Log(message, exception, OperationProcessLevel.Error);
		}

		public static void Debug(this ILogger logger, string message)
		{
			logger.Log(message, OperationProcessLevel.Debug);
		}

		public static void Debug(this ILogger logger, Func<String> messageGetter)
		{
			logger.Log(messageGetter, OperationProcessLevel.Debug);
		}

		public static void Warn(this ILogger logger, string message)
		{
			logger.Log(message, OperationProcessLevel.Warning);
		}

		public static void Warn(this ILogger logger, string format, params object[] args)
		{
			logger.LogFormat(OperationProcessLevel.Warning, format, args);
		}

		public static void Warn(this ILogger logger, Func<String> messageGetter)
		{
			logger.Log(messageGetter, OperationProcessLevel.Warning);
		}

		public static void Info(this ILogger logger, string message)
		{
			logger.Log(message, OperationProcessLevel.Infomation);
		}

		public static void Info(this ILogger logger, string format, params object[] args)
		{
			logger.LogFormat(OperationProcessLevel.Infomation, format, args);
		}

		public static void Info(this ILogger logger, Func<String> messageGetter)
		{
			logger.Log(messageGetter);
		}
	}
}
